package com.gitee.service.openapi;

import com.gitee.gateway.core.utils.AsyncInputStream;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.openapi.RouterBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * URL Router center
 */
class Handlers {

    public final static String OPENAPI = "/openapi.yaml";
    private final RouterBuilder builder;
    private final OpenApiHandler openApiHandler;

    public Handlers(RouterBuilder builder, OpenApiHandler openApiHandler) {
        this.builder = builder;
        this.openApiHandler = openApiHandler;
    }

    /**
     * openapi router
     *
     * @param category category
     * @param action   action
     * @return Handler
     */
    public final Handler<RoutingContext> handle(String category, String action) {
        return switch (category) {
            case "welcome" -> this::welcome;                // Show welcome message
            case "json" -> this::json;                      // Export openapi definitions in JSON
            case "yaml" -> this::yaml;                      // Export openapi definitions in YAML
            default -> openApiHandler.handle(category, action);
        };
    }

    void welcome(RoutingContext context) {
        switch (context.getAcceptableContentType()) {
            case "application/x-yaml" -> yaml(context);
            case "application/json" -> json(context);
            default -> context.end("Ready!");
        }
    }

    /**
     * Export openapi definitions in YAML
     */
    void yaml(RoutingContext context) {
        InputStream stream = Handlers.class.getResourceAsStream(OPENAPI);
        var response = context.response();
        try {
            response.putHeader("content-type", "application/x-yaml")
                    .putHeader("Content-Length", String.valueOf(stream.available()))
                    .putHeader("Cache-Control", "private, max-age=86400");//缓存一天
        } catch (IOException e) {
            context.fail(e);
            return;
        }
        var iStream = new AsyncInputStream(context, stream);
        iStream.handler(h -> {
            response.write(h);
            if (response.writeQueueFull()) {
                iStream.pause();
                response.drainHandler(v -> iStream.resume());
            }
        }).endHandler(v -> {
            iStream.close();
            context.response().end();
        });
    }

    /**
     * Export openapi definitions in JSON
     */
    void json(RoutingContext context) {
        boolean pretty = context.queryParams().contains("pretty");
        if (pretty) {
            context.response()
                    .putHeader("content-type", "application/json")
                    .end(builder.getOpenAPI().getOpenAPI().encodePrettily());
        } else
            context.json(builder.getOpenAPI().getOpenAPI());
    }

}
